import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JComponent;

@SuppressWarnings("serial")
public class Piece extends JComponent {

	public final static int HEIGHT = 100;
	public final static int WIDTH = 100;
	private final static int SIZE_CARRE = 20;
	private Forme model;
	private Sens sens;
	private List<Rectangle> rects;
	private int x;
	private int y;

	public Piece(Forme model, int x, int y) {
		this.model = model;
		this.sens = Sens.UP;
		rects = new ArrayList<Rectangle>();
		this.x = x;
		this.y = y;
		setPreferredSize(new Dimension(HEIGHT, WIDTH));
	}
	
	public Sens getSens() {
		return sens;
	}
	
	public List<Rectangle> getRects(){
		return rects;
	}

	public int getX() {
		return x;
	}

	public int getY() {
		return y;
	}
	
	public Forme getModel() {
		return model;
	}

	
	public void setSens(Sens sens) {
		this.sens = sens;
	}

	public void setY(int y) {
		this.y = y;
	}

	public void setX(int x) {
		this.x = x;
	}
	
	public void prochainSens() {
		switch(sens) {
		case UP:
			setSens(Sens.RIGHT);
			break;
		case RIGHT:
			setSens(Sens.DOWN);
			break;
		case DOWN:
			setSens(Sens.LEFT);
			break;
		case LEFT:
			setSens(Sens.UP);
			break;
		}
	}
	
	public void updatePosition(int x) {
		int delta = this.x - x;
		this.x = x;
		
		for(Rectangle r : this.getRects()){
			r.setLocation(r.x - delta, r.y);
		}
	}
	
	public boolean croiseAutrePiece(Piece p){
		if(p == null){
			throw new IllegalArgumentException();
		}


		for(Rectangle r : rects){
			for(Rectangle r2 : p.getRects()){
				if(r.intersects(r2)){
					return true;
				}
			}
		}
		return false;
	}

	public void paintComponent(Graphics g) {
		Graphics2D g2d = (Graphics2D) g;
		switch (model) {
		case F:
			paintF(g2d);
			break;
		case I:
			paintI(g2d);
			break;
		case L:
			paintL(g2d);
			break;
		case N:
			paintN(g2d);
			break;
		case P:
			paintP(g2d);
			break;
		case T:
			paintT(g2d);
			break;
		case U:
			paintU(g2d);
			break;
		case V:
			paintV(g2d);
			break;
		case W:
			paintW(g2d);
			break;
		case X:
			paintX(g2d);
			break;
		case Y:
			paintY(g2d);
			break;
		case Z:
			paintZ(g2d);
			break;
		}
	}

	/**********************************************************/
	/************* Fonctions de cr�ation des formes *************/
	/**********************************************************/
	private void paintF(Graphics2D g) {
		Color color = model.getCouleur();
		switch(sens) {
		case UP:
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x + 2 * SIZE_CARRE, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			break;
		case RIGHT:
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			break;
		case DOWN:
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x, y + 2 * SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			break;
		case LEFT:
			carre(g, x, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			break;
		}
	}

	private void paintI(Graphics2D g) {
		Color color = model.getCouleur();
		switch(sens) {
		case UP:
		case DOWN:
			carre(g, x, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x, y + 2 * SIZE_CARRE, color);
			carre(g, x, y + 3 * SIZE_CARRE, color);
			carre(g, x, y + 4 * SIZE_CARRE, color);
			break;
		case RIGHT:
		case LEFT:
			carre(g, x, y, color);
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x + 2 * SIZE_CARRE, y, color);
			carre(g, x + 3 * SIZE_CARRE, y, color);
			carre(g, x + 4 * SIZE_CARRE, y, color);
			break;
		}
	}

	private void paintL(Graphics2D g) {
		Color color = model.getCouleur();
		switch(sens) {
		case UP:
			carre(g, x, y, color);
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x + 2 * SIZE_CARRE, y, color);
			carre(g, x + 3 * SIZE_CARRE, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			break;
		case RIGHT:
			carre(g, x, y, color);
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + 3 *SIZE_CARRE, color);
			break;
		case DOWN:
			carre(g, x + 3 * SIZE_CARRE, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 3 * SIZE_CARRE, y + SIZE_CARRE, color);
			break;
		case LEFT:
			carre(g, x, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x, y + 2 * SIZE_CARRE, color);
			carre(g, x, y + 3 * SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + 3 * SIZE_CARRE, color);
			break;
		}
	}

	private void paintN(Graphics2D g) {
		Color color = model.getCouleur();
		switch(sens) {
		case UP:
			carre(g, x, y, color);
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x + 2 * SIZE_CARRE, y, color);
			carre(g, x + 2 * SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 3 * SIZE_CARRE, y + SIZE_CARRE, color);
			break;
		case RIGHT:
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x +  SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			carre(g, x, y + 2 * SIZE_CARRE, color);
			carre(g, x, y + 3 *SIZE_CARRE, color);
			break;
		case DOWN:
			carre(g, x, y, color);
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x + 2 * SIZE_CARRE, y, color);
			carre(g, x + 2 * SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 3 * SIZE_CARRE, y + SIZE_CARRE, color);
			break;
		case LEFT:
			carre(g, x, y, color);
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x + 2 * SIZE_CARRE, y, color);
			carre(g, x + 2 * SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 3 * SIZE_CARRE, y + SIZE_CARRE, color);
			break;
		}
	}

	private void paintP(Graphics2D g) {
		Color color = model.getCouleur();
		switch(sens) {
		case UP:
			carre(g, x, y, color);
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x + 2 * SIZE_CARRE, y, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + SIZE_CARRE, color);
			break;
		case RIGHT:
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x, y + 2 * SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			break;
		case DOWN:
			carre(g, x, y, color);
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + SIZE_CARRE, color);
			break;
		case LEFT:
			carre(g, x, y, color);
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x, y + 2 * SIZE_CARRE, color);
			break;
		}
	}

	private void paintT(Graphics2D g) {
		Color color = model.getCouleur();
		switch(sens) {
		case UP:
			carre(g, x, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x, y + 2 * SIZE_CARRE, color);
			break;
		case RIGHT:
			carre(g, x, y, color);
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x + 2 * SIZE_CARRE, y, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			break;
		case DOWN:
			carre(g, x + 2 * SIZE_CARRE, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			break;
		case LEFT:
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x, y +  2 *SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			break;
		}
	}

	private void paintU(Graphics2D g) {
		Color color = model.getCouleur();
		switch(sens) {
		case UP:
			carre(g, x, y, color);
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x + 2 * SIZE_CARRE, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + SIZE_CARRE, color);
			break;
		case RIGHT:
			carre(g, x, y, color);
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x, y + 2 * SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			break;
		case DOWN:
			carre(g, x, y, color);
			carre(g, x + 2 * SIZE_CARRE, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + SIZE_CARRE, color);
			break;
		case LEFT:
			carre(g, x, y, color);
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x, y + 2 * SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y +  2 *SIZE_CARRE, color);
			break;
		}
	}

	private void paintV(Graphics2D g) {
		Color color = model.getCouleur();
		switch(sens) {
		case UP:
			carre(g, x, y, color);
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x + 2 * SIZE_CARRE, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x, y + 2 * SIZE_CARRE, color);
			break;
		case RIGHT:
			carre(g, x, y, color);
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x + 2 * SIZE_CARRE, y, color);
			carre(g, x + 2 * SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			break;
		case DOWN:
			carre(g, x + 2 * SIZE_CARRE, y, color);
			carre(g, x + 2 * SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x, y + 2 * SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			break;
		case LEFT:
			carre(g, x, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x, y + 2 * SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			break;
		}
	}

	private void paintW(Graphics2D g) {
		Color color = model.getCouleur();
		switch(sens) {
		case UP:
			carre(g, x, y, color);
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			break;
		case RIGHT:
			carre(g, x + 2 *SIZE_CARRE, y, color);
			carre(g, x + 2 *SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			carre(g, x, y + 2 * SIZE_CARRE, color);
			break;
		case DOWN:
			carre(g, x, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			break;
		case LEFT:
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x + 2 * SIZE_CARRE, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x, y + 2 * SIZE_CARRE, color);
			break;
		}
	}

	private void paintX(Graphics2D g) {
		Color color = model.getCouleur();
		carre(g, x + SIZE_CARRE, y, color);
		carre(g, x, y + SIZE_CARRE, color);
		carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
		carre(g, x + 2 * SIZE_CARRE, y + SIZE_CARRE, color);
		carre(g, x + SIZE_CARRE, y + 2 * SIZE_CARRE, color);
	}

	private void paintY(Graphics2D g) {
		Color color = model.getCouleur();
		switch(sens) {
		case UP:
			carre(g, x, y, color);
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x + 2 * SIZE_CARRE, y, color);
			carre(g, x + 3 * SIZE_CARRE, y, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			break;
		case RIGHT:
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + 3 * SIZE_CARRE, color);
			break;
		case DOWN:
			carre(g, x + 2 * SIZE_CARRE, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 3 * SIZE_CARRE, y + SIZE_CARRE, color);
			break;
		case LEFT:
			carre(g, x, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x, y + 2 * SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			carre(g, x, y + 3 * SIZE_CARRE, color);
			break;
		}
	}

	private void paintZ(Graphics2D g) {
		Color color = model.getCouleur();
		switch(sens) {
		case UP:
		case DOWN:
			carre(g, x, y, color);
			carre(g, x, y + SIZE_CARRE, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x + 2 * SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			break;
		case RIGHT:
		case LEFT:
			carre(g, x + SIZE_CARRE, y, color);
			carre(g, x + 2 * SIZE_CARRE, y, color);
			carre(g, x + SIZE_CARRE, y + SIZE_CARRE, color);
			carre(g, x, y + 2 * SIZE_CARRE, color);
			carre(g, x +SIZE_CARRE, y + 2 * SIZE_CARRE, color);
			break;
		}
	}

	/**********************************************************/

	// Fonction qui dessine des petits carre pour faire des formes s'allignant
	// sur la grille
	private void carre(Graphics g, int x, int y, Color color) {
		g.setColor(color);
		if(rects.size() >= 5){
			rects.clear();
		}
		rects.add(new Rectangle(x, y, SIZE_CARRE, SIZE_CARRE));
		g.fillRect(x, y, SIZE_CARRE, SIZE_CARRE);
		g.setColor(Color.black);
		g.drawRect(x, y, SIZE_CARRE, SIZE_CARRE);
	}
}
